/*
 *  Copyright (C) 2008      Tri Tech Information Systems Inc.
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#ifndef __PYXX_PY_QHASH_H__
#define __PYXX_PY_QHASH_H__

#include <QHash>
#include <boost/python.hpp>

template< class _T >
struct PyHash
{
    typedef _T Hash;
    typedef typename Hash::key_type Key;
    typedef typename Hash::mapped_type Val;

    static const Val get( const Hash& self, const Key idx )
    {
        if( !self.contains(idx) )
        {
            PyErr_SetString( PyExc_KeyError, "QHash key not found" );
            boost::python::throw_error_already_set();
        }
        return self.value( idx );
    }

    static void set( Hash& self, const Key idx, const Val val )
    {   self.insert( idx, val );
    }

    static void del( Hash& self, const Key idx )
    {   self.remove( idx );
    }

    static bool in( const Hash& self, const Key idx )
    {   return self.contains( idx );
    }

    static QList<Key> keys( const Hash& self )
    {
        return self.keys();
//        boost::python::list r;
//        foreach( const Key& k, self.keys() )
//            r.append( k );
//        return r;
    }

    static QList<Val> values( const Hash& self )
    {
        return self.values();
//        boost::python::list r;
//        foreach( const Val& v, self.values() )
//            r.append( v );
//        return r;
    }

    static boost::python::list items( const Hash& self )
    {
        boost::python::list r;
        for( typename Hash::const_iterator it = self.begin();
                it != self.end(); ++it )
            r.append( boost::python::make_tuple(it.key(), it.value()) );
        return r;
    }
};

template< class _T >
struct PyMultiHash :
    public PyHash< _T >
{
    typedef _T Hash;
    typedef typename Hash::key_type Key;
    typedef typename Hash::mapped_type Val;

    static QList<Val> get( const Hash& self, const Key idx )
    {
        if( !self.contains(idx) )
        {
            PyErr_SetString( PyExc_KeyError, "QMultiHash key not found" );
            boost::python::throw_error_already_set();
        }
        return self.values( idx );
    }
};

template< class K, class V >
void Wrap_QHash()
{
    using namespace boost::python;

    class_< QHash<K,V> >( typeid(QHash<K,V>).name(), no_init )
        .def( "__len__", &QHash<K,V>::size )
        .def( "__getitem__", &PyHash< QHash<K,V> >::get )
        .def( "__setitem__", &PyHash< QHash<K,V> >::set )
        .def( "__delitem__", &PyHash< QHash<K,V> >::del )
        .def( "clear", &QHash<K,V>::clear )
        .def( "__contains__", &PyHash< QHash<K,V> >::in )
        .def( "has_key", &PyHash< QHash<K,V> >::in )
        .def( "keys", &PyHash< QHash<K,V> >::keys )
        .def( "values", &PyHash< QHash<K,V> >::values )
        .def( "items", &PyHash< QHash<K,V> >::items )
        ;
}

template< class K, class V >
void Wrap_QMultiHash()
{
    using namespace boost::python;

    class_< QMultiHash<K,V> >( typeid(QMultiHash<K,V>).name(), no_init )
        .def( "__len__", &QMultiHash<K,V>::size )
        .def( "__getitem__", &PyMultiHash< QMultiHash<K,V> >::get )
        .def( "__setitem__", &PyMultiHash< QMultiHash<K,V> >::set )
        .def( "__delitem__", &PyMultiHash< QMultiHash<K,V> >::del )
        .def( "clear", &QMultiHash<K,V>::clear )
        .def( "__contains__", &PyMultiHash< QMultiHash<K,V> >::in )
        .def( "has_key", &PyMultiHash< QMultiHash<K,V> >::in )
        .def( "keys", &PyMultiHash< QMultiHash<K,V> >::keys )
        .def( "values", &PyMultiHash< QMultiHash<K,V> >::values )
        .def( "items", &PyMultiHash< QMultiHash<K,V> >::items )
        ;
}

#endif
